#ifndef ns_cope_packet_h
#define ns_cope_packet_h

#include "packet.h"

#define COPE_DATA 0
#define COPE_CTRL 1
#define COPE_RETX 2

#define COPE_LEN 10

/*
 * Some members of the header have been reodered, compare to the structure
 * the paper provides (Figure 5), to save memory by data structure alignment
 */

typedef struct {
    int pkt_id_; //packet ID: 32-bit hash of its ip addr and ip seq number
    int nexthop_; //MAC addr of the native packet's nexthop
    u_int16_t local_seq_num_; /*
			       * sequence number of packet sent to that neighbor
			       * the value is the same as Local_PKT_SEQ_NUM
			       * node can use it to identify which packet
			       */
    u_int8_t retx_counter_; // counter for retransmission
    Packet** ppkt_addr_;
} hdr_xored_t;
    
typedef struct {
    nsaddr_t src_ip_; //source IP of the reported packets
    u_int16_t last_pkt_; //last IP seq-number of packet heard from that source
    u_int8_t bit_map_; //bit-map of recently heard packets from that source
} hdr_report_t;
    
typedef struct {
    int neighbor_; //MAC address of neighbors
    u_int16_t last_ack_; //last ack seq-number received from that neighbor
    u_int8_t ack_map_; //bit-map of received/missing packets from that neighbor
} hdr_ack_t;


struct hdr_cope {
    u_int8_t ctype_; //non-control packet by default

    u_int8_t encoded_num_; //number of native packets
    u_int8_t report_num_; //number of the reports
    u_int8_t ack_num_; //number of acks

    hdr_xored_t xoreds_[COPE_LEN];
    hdr_report_t reports_[COPE_LEN];
    hdr_ack_t acks_[COPE_LEN];
    
    static int offset_;
    inline static int& offset() { return offset_; }
    inline static struct hdr_cope* access(const Packet *p) {
    	return (struct hdr_cope*) p->access(offset_);
    }

    inline u_int8_t& ack_num() { return ack_num_; }

    /* // get the length of cope header */
    /* inline u_int32_t cope_hdrlen() { */
    /* 	return 4 * sizeof(u_int8_t) */
    /* 	    + (COPE_LEN * sizeof(hdr_xored_t)) */
    /* 	    + (COPE_LEN * sizeof(hdr_report_t)) */
    /* 	    + (COPE_LEN * sizeof(hdr_ack_t)); */
    /* } */

hdr_cope() : ctype_(COPE_DATA) {} 

};


#endif
